// exception.cc 
/*
Modifications by: Paul Krushinskie
Modified read
Added ls, open, close, create and pwd
*/

#include <stdio.h>        // FA98
#include "copyright.h"
#include "system.h"
#include "syscall.h"
#include "addrspace.h"   // FA98
#include "sysdep.h"   // FA98
#include "utility.h"
#include "console.h"

#define TransferSize 	10

extern void Print(char *file), PerformanceTest(void);

// begin FA98

int SRead(int addr, int size, int id);
void SWrite(char *buffer, int size, int id);

// end FA98

int numID = 1;
int numOPEN = -1;
openedList *myOFiles = new openedList();
bool hasL = false;

// vars for 4
char *newArg1 = new char[100];
char *newArg2 = new char[100];
char *newArg3 = new char[100];
bool cat2 = false;


//----------------------------------------------------------------------
// ExceptionHandler
// 	Entry point into the Nachos kernel.  Called when a user program
//	is executing, and either does a syscall, or generates an addressing
//	or arithmetic exception.
//
// 	For system calls, the following is the calling convention:
//
// 	system call code -- r2
//		arg1 -- r4
//		arg2 -- r5
//		arg3 -- r6
//		arg4 -- r7
//
//	The result of the system call, if any, must be put back into r2. 
//
// And don't forget to increment the pc before returning. (Or else you'll
// loop making the same system call forever!
//
//	"which" is the kind of exception.  The list of possible exceptions 
//	are in machine.h.
//----------------------------------------------------------------------

void processCreator(int arg){
	//printf("Hit Process Creator");
	if (threadToBeDestroyed != NULL){
		delete threadToBeDestroyed;
		threadToBeDestroyed = NULL;
	}
	//printf("\n\nINIT REGS\n\n");
//	printf("CURRENT THREAD RUNNING: %s\n", currentThread->getName());
	currentThread->space->InitRegisters();
	//printf("\n\nRESTORE STATE\n\n");
	currentThread->space->RestoreState();		// load page table register
	//printf("RUNNING PROCESS\n");
	machine->Run();								// jump to the user program
	ASSERT(FALSE);								// machine->Run never returns
}


void
ExceptionHandler(ExceptionType which)
{
	int type = machine->ReadRegister(2);

	int arg1 = machine->ReadRegister(4);
	int arg2 = machine->ReadRegister(5);
	int arg3 = machine->ReadRegister(6);
	int Result;
	int i, j;
	char *ch = new char [500];
	int wallE = 0;				// -----------------------------
	
	// variable for join
	bool validID = true;
	
	int numShouts;
	
	// variables for execute
	int buffadd;
	int fix;
	int processID = 0;
	OpenFile *executable;
	char *filename = new char[100];
	int testChar;
	char *threadID = new char[20];
	AddrSpace *space;
	AddrSpace *tempSpace;
	Thread* t;
	
	
	// variables for task 2 proj 3
	int fileSize = 0;
	char *myFile = new char[100];
	OpenFile *openedFile;
	int checkIt;
	OpenFile *tempOpen;
	char testLS_L[5];
	sprintf(testLS_L, "ls -l");
	char myTempFile[100];
	char myTEST[100];
	sprintf(myTEST, "ls -l");
	bool canCreate;
	
	// variables for project 4	
	char helpGetArg[100];
	int nameLen;
	OpenFile *openedFile1;
	OpenFile *openedFile2;
	OpenFile *openedFile3;
	bool didSYSRM = true;
	bool useParsing = false;
	int newDir1;
	int newDir2;
	int specCount;
	int getSectNew1;
	int getSectNew2;
	int goThrough = 0;
	char *getFile12 = new char[16];
	char *specCharGetter;
	OpenFile* mySpecialOPFile;
	
	
	switch ( which )
	{
	case NoException :
		break;
	case SyscallException :
		// for debugging, in case we are jumping into lala-land
		// Advance program counters.
		type = machine->ReadRegister(2);
		machine->registers[PrevPCReg] = machine->registers[PCReg];
		machine->registers[PCReg] = machine->registers[NextPCReg];
		machine->registers[NextPCReg] = machine->registers[NextPCReg] + 4;

		if(newArg1 == NULL){
		//	printf("NEW ARG1: %s \n", newArg1);
			delete newArg1;
			newArg1 = new char[100];
		}
		
		if(newArg2 == NULL){
			delete newArg2;
			newArg2 = new char[100];
		}
		
		if(newArg3 == NULL){
			delete newArg3;
			newArg3 = new char[100];
		}
		
		if(filename == NULL){
			filename = new char[100];
		}
		
		switch ( type )
		{
		 case SC_Exec:
			
		//	printf("System Call: Exec\n");
		//	printf("Current Thread: %s\n", currentThread->getName());
			
			DEBUG('t', "\n\n\nSTARTING EXEC\n\n\n");
			//printf("In Exec");
			//currentThread->Finish();
			/*write code for handling Exec*/
			/*----------------------------*/
			
			DEBUG('t', "STARTING EXEC\n");
			
			DEBUG('t', "THE SPACE FROM ADDRESS SPACE %d\n", space);
				
			
			interrupt->SetLevel(IntOff);
			
			buffadd = machine->ReadRegister(4);	/* only one argument, so that's in R4 */
			
			// find a proper place to free this allocation
			
			//printf("Enter the filename: ");
			//scanf("%s", filename);
			//printf("%s", filename);
			/*now filename contains the file */			
		
			if(!machine->ReadMem(buffadd,1,&testChar)){
				return; // no valid filename
			}
		//	if(hasL == true){
		//		printf("before 173\n");
		//	}
			
			while(testChar != 0){
				filename[wallE] = (char)testChar;
				myTempFile[wallE] = filename[wallE];
				buffadd+=1;
				wallE++;
				if(!machine->ReadMem(buffadd, 1, &testChar)) return;	// it broke so leave
			}
			filename[wallE] = (char)0;
			
			nameLen = strlen(filename);
			buffadd = machine->ReadRegister(4);
			
			for(int gog = 0; gog < nameLen; gog++){						// get rid of old stuff
				machine->WriteMem((buffadd+gog), 1, 0);
			}
			
			//printf("Filename: %s \n", filename);

			
		//	if(hasL == true){
			//	printf("before 186\n");
		//	}
			//printf("this is the filename %s \n", filename);
			//printf("the is myTempFile %s \n", myTempFile);
			
		//	printf("Filename IS : %s\n", filename);
			
			if(strcmp(myTEST, filename) == 0){
			//	fileSystem->AllowSysCall();
				sprintf(filename, "ls");
				hasL = true;
			}
			
			if(filename[0] == 'c' && filename[1] == 'a' && filename[2] == 't'){
				fileSystem->AllowSysCall();
				int count = 0;
				int p = 4;
				
			//	printf("filename %s \n", filename);
				
				while((filename[p] != ' ' || filename[p] != 0) && (count+4 < strlen(filename))){
					newArg1[count] = filename[p];		// get first argument
					
					//printf("filename[%d] is %c \n", p, filename[p]);
					//printf("newArg1[%d] is %c \n", count, newArg1[count]);
					p++;
					count++;
					if(filename[p] == ' '){
						break;
					}
					if(filename[p] == 0){
						break;
					}
				}
				if(strlen(newArg1) > count){
					for(int checkerS = count; checkerS < strlen(newArg1); checkerS++){
						newArg1[checkerS] = '\0';
					}
				}
			//	printf("AFTER FIRST WHILE ARG1 IS: %s \n", newArg1);
			//	printf("Did first while\n");
				int test1 = p + 1;
				if(filename[test1] != 0 && (test1 < strlen(filename))){
					cat2 = true;
					int l = 5+strlen(newArg1);
					count = 0;
					while((filename[l] != ' ' || filename[l] != 0) && (l < strlen(filename))){			// get second argument
						newArg2[count] = filename[l];
						l++;
						count++;
						if(filename[l] == ' '){
							break;
						}
					}
				if(strlen(newArg2) > count){
					for(int checkerZ = count; checkerZ < strlen(newArg2); checkerZ++){
						newArg2[checkerZ] = '\0';
					}
				}
			//		printf("second while\n");
					l++;
					count = 0;
					while(l < strlen(filename) && (l < strlen(filename))){			// get third argument
						newArg3[count] = filename[l];
						l++;
						count++;
					}
					if(strlen(newArg3) > count){
						for(int checkerA = count; checkerA < strlen(newArg3); checkerA++){
							newArg3[checkerA] = '\0';
						}
					}
					
				//	printf("Arg1: %s \n", newArg1);
				//	printf("Arg2: %s \n", newArg2);
				//	printf("Arg3: %s \n", newArg3);
					
			//		printf("third while\n");
				}
				
			//	printf("FILENAME BEFORE %s \n", filename);
			//	printf("Done getting args\n");
				delete filename;
				filename = new char[100];
				//printf("Arg1 BEFORE CAT CALL: %s\n", newArg1);
				//printf("Arg2 BEFORE CAT CALL: %s\n", newArg2);
			///	printf("Arg3 BEFORE CAT CALL: %s\n", newArg3);
				sprintf(filename, "cat");
			//	printf("FILENAME AFTER %s \n", filename);
			}
			
			else if(filename[0] == 's' && filename[1] == 'h' && filename[2] == 'e' && filename[3] == 'l' && filename[4] == 'l'){
				printf("NO\n");
				delete filename;
				filename = new char[100];
				sprintf(filename, "\0");
			}
			
			if(filename[0] == 'l' && filename[1] == 's' && filename[2] == '\0'){
			//	printf("YO YOU ARE DOING LS\n");
				
				fileSystem->AllowSysCall();
			}
			
			else if(filename[0] == 'm' && filename[1] == 'k' && filename[2] == 'd' && filename[3] == 'i' && filename[4] == 'r'){
				fileSystem->AllowSysCall();
				int c = 0;
				while(filename[6+c] != 0 || (6+c) < strlen(filename)){			
					newArg1[c] = filename[6+c];		// get arg1 for mkdir
					c++;
				}
				
				if(strlen(newArg1) > c){
					for(int checkerB = c; checkerB < strlen(newArg1); checkerB++){
						newArg1[checkerB] = '\0';
					}
				}
				
			///	printf("NewArg1 %s. \n", newArg1);
				
				
			//	printf("After while\n");
				delete filename;
				filename = new char[100];
				sprintf(filename, "mkdir");

			}
			
			else if(filename[0] == 'r' && filename[1] == 'm' && filename[2] == 'd' && filename[3] == 'i' && filename[4] == 'r'){
				fileSystem->AllowSysCall();
				int v = 0;
				while((filename[6+v] != 0) || (6+v) < strlen(filename)){			
					newArg1[v] = filename[6+v];		// get arg1 for mkdir
					v++;
				}
				if(strlen(newArg1) > v){
					for(int checker = v; checker < strlen(newArg1); checker++){
						newArg1[checker] = '\0';
					}
				}
			//	printf("NewArg1 %s. \n", newArg1);
				
				delete filename;
				filename = new char[100];
				sprintf(filename, "rmdir");

			}
			
			else if(filename[0] == 'c' && filename[1] == 'd'){
				fileSystem->AllowSysCall();
				int q = 0;
				while(filename[3+q] != 0 || (3+q) < strlen(filename)){			
					newArg1[q] = filename[3+q];		// get arg1 for mkdir
					q++;
				}
				if(strlen(newArg1) > q){
					for(int checker = q; checker < strlen(newArg1); checker++){
						newArg1[checker] = '\0';
					}
				}
				//printf("NewArg1 %s. \n", newArg1);
				
				delete filename;
				filename = new char[100];
				sprintf(filename, "cd");

			}
			
			else if(filename[0] == 'r' && filename[1] == 'm'){
				fileSystem->AllowSysCall();
				int g = 0;
				while(filename[3+g] != 0 || (3+g) < strlen(filename)){			
					printf("%c", filename[3+g]);
					newArg1[g] = filename[3+g];		// get arg1 for mkdir
					g++;
				}
				if(strlen(newArg1) > g){
					for(int checker = g; checker < strlen(newArg1); checker++){
						newArg1[checker] = '\0';
					}
				}
				//printf("NewArg1 %s. \n", newArg1);
				
				delete filename;
				filename = new char[100];
				sprintf(filename, "rm");
			}
			
			else if(filename[0] == 'c' && filename[1] == 'p'){
				fileSystem->AllowSysCall();
				int h = 0;
				while(filename[3+h] != ' ' && (3+h) < strlen(filename)){			
					newArg1[h] = filename[3+h];		// get arg1 for mkdir
					h++;
				}
				if(strlen(newArg1) > h){
					for(int checker = h; checker < strlen(newArg1); checker++){
						newArg1[checker] = '\0';
					}
				}
				int gjk = 4+strlen(newArg1);
				int count = 0;
				while((filename[gjk] != ' ' || filename[gjk] != 0) && (gjk < strlen(filename))){			// get second argument
					newArg2[count] = filename[gjk];
					gjk++;
					count++;
					if(filename[gjk] == ' '){
						break;
					}
				}

				if(strlen(newArg2) > count){
					for(int checkerZ = count; checkerZ < strlen(newArg2); checkerZ++){
						newArg2[checkerZ] = '\0';
					}
				}
				
				
				
				//printf("NewArg1 %s. \n", newArg1);
				//printf("NewArg2 %s. \n", newArg2);
				
				delete filename;
				filename = new char[100];
				sprintf(filename, "cp");
			}
			
			else if(filename[0] == 'c' && filename[1] == 'r' && filename[2] == 'e' && filename[3] == 'a' && filename[4] == 't' && filename[5] == 'e'){
				fileSystem->AllowSysCall();
			/*	int h = 0;
				while(filename[3+h] != 0 || (3+h) < strlen(filename)){			
					newArg1[h] = filename[3+h];		// get arg1 for mkdir
					h++;
				}
				if(strlen(newArg1) > h){
					for(int checker = h; checker < strlen(newArg1); checker++){
						newArg1[checker] = '\0';
					}
				}
				
				printf("NewArg1 %s. \n", newArg1);
				*/
				delete filename;
				filename = new char[100];
				sprintf(filename, "create");
			}
			
			else if(filename[0] == 'm' && filename[1] == 'v'){
				fileSystem->AllowSysCall();
				int h = 0;
				while(filename[3+h] != ' ' && (3+h) < strlen(filename)){			
					newArg1[h] = filename[3+h];		// get arg1 for mkdir
					h++;
				}
				if(strlen(newArg1) > h){
					for(int checker = h; checker < strlen(newArg1); checker++){
						newArg1[checker] = '\0';
					}
				}
				int gjk = 4+strlen(newArg1);
				int count = 0;
				while((filename[gjk] != ' ' || filename[gjk] != 0) && (gjk < strlen(filename))){			// get second argument
					newArg2[count] = filename[gjk];
					gjk++;
					count++;
					if(filename[gjk] == ' '){
						break;
					}
				}

				if(strlen(newArg2) > count){
					for(int checkerZ = count; checkerZ < strlen(newArg2); checkerZ++){
						newArg2[checkerZ] = '\0';
					}
				}
				
				
				
				//printf("NewArg1 %s. \n", newArg1);
				//printf("NewArg2 %s. \n", newArg2);
				
				delete filename;
				filename = new char[100];
				sprintf(filename, "mv")
			}
			
			if(filename[0] == 'p' && filename[1] == 'w' && filename[2] == 'd'){
				fileSystem->AllowSysCall();
				
			}
			
			
			if(strchr(filename, '!') || strchr(filename, '@') || strchr(filename, '#') || strchr(filename, '$') || 
			strchr(filename, '%') || strchr(filename, '^') || strchr(filename, '&') || strchr(filename, '*') || 
			strchr(filename, '(') || strchr(filename, ')') || strchr(filename, '-') || strchr(filename, '_') || 
			strchr(filename, '=') || strchr(filename, '+')){
				sprintf(filename, "\0");
			}
			
			if(strlen(filename) >= 9){
				sprintf(filename, "\0");
			}
			
		//	printf("USING FILE: %s\n", filename);
		//	DEBUG('t', "did it\n");
			DEBUG('t', "THIS IS THE FILE NAME: %s", filename);
		
		//	if(hasL == true){
		//		printf("Something is wrong\n");
		//	}
		//	if(filename == testLS_L){
			//	printf("IT had a -l\n");
			//	filename[0] = '\0';
			//	printf("This is the filename now %s\n", filename);
			//	sprintf(filename, "ls");
			//	hasL = true;
		//	}
		

			executable = fileSystem->Open(filename);	
			
			if(executable != NULL){
			//	printf("\n\n\n\n\nTATAS\n\n\n\n\n\n\n\n");
				tempSpace = new AddrSpace(executable);
			//	printf("IN IF\n");			
				sprintf(threadID, "%d", numID);		
		//		printf("numID %d\n", numID);
		//		printf("threadID %s\n", threadID);
				
			//	printf("making thread\n");
				t = new Thread(threadID);
			//	printf("setting parent\n");
				t->setParent(currentThread);
			//	printf("setting ID\n");
				t->setID(numID);
			//	printf("Adding child\n");
				currentThread->addChild(t);
			//	printf("MADE THREAD SET ITS PARENT ADDED CHILD\n");
				
			//	printf("JUST MADE THREAD T AND ITS ID IS %d \n", t->getID());
			//	printf("ITS PARENTS ID IS %d\n", currentThread->getID());
				
				
			//	printf("the key after adding: %d\n\n",currentThread->firstChild->key);
				t->space = tempSpace;
			
				DEBUG('t', "THE SPACE FROM ADDRESS SPACE %d\n", space);
					
			//scanf("%d", &numShouts);
			
				processID = t->getID(); // create this function by yourself
				t->addExec(executable);
				t->Fork(processCreator, processID); //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
				numID++;
				//t->setStatus(READY);
				machine->WriteRegister(2, processID);
			}
			
			else{
			//	printf("IN THE ELSE\n");
				machine->WriteRegister(2, 9001);
				break;
			}
			
		//	printf("GOT HERE");
		//	printf("After the fork\n");
			//scheduler->Run(t); ------------------------SEGFAULT
			/*be careful to on and off interrupts at proper places*/
			//interrupt->SetLevel(IntOn);
			/*----------------------------*/
			
			/* return the process id for the newly created process, return value
			is to write at R2	*/
			/* routine task - do at last -- generally mainpulate PCReg,
			PrevPCReg, NextPCReg so that they point to proper place	*/
		break;
		
		case SC_Yield:
		//	printf("System Call: Yield\n");
		//	printf("Current Thread: %s\n", currentThread->getName());
			interrupt->SetLevel(IntOn);
			currentThread->Yield();
		break;
		
		case SC_Join :
			interrupt->SetLevel(IntOff);
		//	printf("System Call: Join\n");
			//printf("Current Thread: %s\n", currentThread->getName());
			// current thread is the parent thread 
			// arg1 is the name of the passed child process
			
			// checking if passed thread is a child of the parent thread
		//	if(currentThread->Children->IsEmpty()){
		//		printf("1\n");
		//		validID = false;			// if no children of course not
		//	}
			
		//	for(ListElement *it = currentThread->firstChild; it != NULL; it = it->next){
		//		//printf("2\n");
		//		if(it->key == arg1){
		//			validID = true;
		//		}				
		//	}
			
			validID = currentThread->children->contains(arg1);
			
			
			// if passed process is valid check if it already exited
			
			if(validID){
			//	printf("3\n");
				DEBUG('t', "Child thread %d is a valid child of parent %d.\n",arg1, (int)currentThread->getName());
				DEBUG('t', "Sleeping parent thread %d.\n\n",(int)currentThread->getName());
				// sleep until all children exit
				//if(!currentThread->Children->IsEmpty()){
				//	printf("Current Thread: %s is Sleeping\n", currentThread->getName());
				//	currentThread->Sleep();
				//}
				
				if(!currentThread->children->isEmpty()){
				//	printf("Current Thread: %s is Sleeping\n", currentThread->getName());
					currentThread->Sleep();
				}
				
			//	printf("CUR THREAD: %s AFTER SLEEP THREAD\n", currentThread->getName());

				DEBUG('t', "Parent thread %d is now awake.\n\n",(int)currentThread->getName());
				
				//when finished return (i assume 0 for successful)
				machine->WriteRegister(2, 0);
				//printf("end of valid ID\n");
				
			}
			// else return -1
			else{
				//printf("4\n");
			//	printf("Thread %d is not a valid child of parent thread %d.\n",arg1, (int)currentThread->getName());
			
				machine->WriteRegister(2, -1);
			} 
			//printf("End of join\n");
			interrupt->SetLevel(IntOn);
			break;
			
			
		
		case SC_Halt :
		//		printf("System Call: Halt\n");
			//	printf("Current Thread: %s\n", currentThread->getName());
				DEBUG('t', "Shutdown, initiated by user program.\n");
				interrupt->Halt();		
			break;

			
		case SC_Exit :
			currentThread->Yield();
		//	printf("System Call: Exit\n");
		//	printf("Current Thread: %s\n", currentThread->getName());
			DEBUG('t', "Exit, initiated by user program.\n");
												
			// need to cleanup properly, removing everything join added
			
			// remove process from list of children
			//run parent thread if last child
			
			// remove this child from parent's list of children
			interrupt->SetLevel(IntOff);	
			
			
			if(currentThread->getParent() != NULL){
		//		printf("THE CURRENT THREAD BEFORE RM IS %d\n", currentThread->getID());
		//		printf("THE CURRENT SUPER THREAD BEFORE RM IS %s\n", currentThread->getName());
		//		printf("THE CURRENT THREAD BEFORE RM IS %d\n", currentThread->getParent()->getID());
		//		printf("THE CURRENT SUPER THREAD BEFORE RM IS %s\n", currentThread->getParent()->getName());
				currentThread->getParent()->removeChild(currentThread);
		//		printf("THE CURR THREAD IS : %s\n", currentThread->getName());
				currentThread->space->RemoveTheMem();
		//			printf("After remove self\n");
					for(int x = 0; x < NumPhysPages; x++){
						if(myBitMap->Test(x) == true){
						//	printf("%d", 1);
						}
						if(myBitMap->Test(x) == false){
					//		printf("%d", 0);
						}
					}
				//	printf("\n");
					
					scheduler->ReadyToRun(currentThread->getParent());
					
					
					
					// set all children's parent pointers to NULL
				//	if(!currentThread->Children->IsEmpty()){						
				//		printf("IN THREAD DESTRUCTION LOOP 1 : %d\n", currentThread->getID());
				//		
				//		for(ListElement* it = currentThread->firstChild; it != NULL ;it = it->next){
				//			((Thread*)it->item)->setParent(NULL);							
				//		}						
				//	}
					
					if(!currentThread->children->isEmpty()){
						for(node* temp = currentThread->children->getFirst(); temp != NULL; temp = temp->next){
							temp->childThread->setParent(NULL);
						}
					}
					
					
					
				//	printf("\nI CRASHED1\n");
						//delete executable;
				//	printf("\nI CRASHED2\n");
					currentThread->removeExec();
					currentThread->Finish();
			}
			if(currentThread->getParent() == NULL){
		//	printf("THE CURR THREAD IS : %s\n", currentThread->getName());
		//	printf("parent is null\n");
			// if current finishing thread is a child, remove the current thread from the parent's list of children

		//		DEBUG('t', "Removing thread \"%s\" from parent \"%s\"'s list of children\n ", 
		//			currentThread->getName(), currentThread->getParent()->getName());
		
				//currentThread->getParent()->removeChild(currentThread);
		
					// if was the last child wake up the parent thread
				//if(currentThread->getParent()->Children->IsEmpty())
				//	currentThread->getParent()->setStatus(READY);
		

			
			//		printf("Before remove self\n");
					currentThread->space->RemoveTheMem();
		//			printf("After remove self\n");
					for(int x = 0; x < NumPhysPages; x++){
						if(myBitMap->Test(x) == true){
							//printf("%d", 1);
						}
						if(myBitMap->Test(x) == false){
							//printf("%d", 0);
						}
					}
					//printf("\n");
					
					// set all children's parent pointers to NULL
				//	if(!currentThread->Children->IsEmpty()){						
				//	//	printf("IN THREAD DESTRUCTION LOOP 2 : %d\n", currentThread->getID());
				//		for(ListElement* it = currentThread->firstChild; it != NULL ;it = it->next){
				//			((Thread*)it->item)->setParent(NULL);							
				//		}						
				//	}
					
					
					if(!currentThread->children->isEmpty()){
						for(node* temp = currentThread->children->getFirst(); temp != NULL; temp = temp->next){
							temp->childThread->setParent(NULL);
						}
					}
					
					currentThread->removeExec();
					currentThread->Finish();

			}	// if it is the first parent
			/*
			else{
				printf("current thread is not the top\n");
				currentThread->space->RemoveTheMem();
				printf("After remove self\n");
				for(int x = 0; x < NumPhysPages; x++){
					if(myBitMap->Test(x) == true){
						printf("%d", 1);
					}
					if(myBitMap->Test(x) == false){
						printf("%d", 0);
					}
				}
				printf("currentThread finish\n");
				currentThread->Finish();
			}
*/			//delete executable;
			interrupt->SetLevel(IntOn);
			// may need to wake up parent thread
			
			break;

			
			case SC_Read :
			
			//	printf("System Call: Read\n");
				if (arg2 <= 0 || arg3 < 0){
					printf("\nRead 0 byte.\n");
				}
				Result = SRead(arg1, arg2, arg3);
				machine->WriteRegister(2, Result);
				DEBUG('t',"Read %d bytes from the open file(OpenFileId is %d)",
				arg2, arg3);
				
			break;

			case SC_Write :
			//	printf("System Call: Write\n");
				for (j = 0; ; j++) {
					if(!machine->ReadMem((arg1+j), 1, &i))
						j=j-1;
					else{
						ch[j] = (char) i;
						if (ch[j] == '\0') 
							break;
					}
				}
				if (j == 0){
				//	printf("\nWrite 0 byte.\n");
					// SExit(1);
				} else {
					DEBUG('t', "\nWrite %d bytes from %s to the open file(OpenFileId is %d).", arg2, ch, arg3);
					SWrite(ch, j, arg3);
				}
			break;
			
			// create a nachos file with the name given
			case SC_Create :
				//fileSize = 0;
				//char *myFile = new char[100];
				//printf("Doing create\n");
				canCreate = true;
				buffadd = machine->ReadRegister(4);	/* only one argument, so that's in R4 */
				if(!machine->ReadMem(buffadd,1,&testChar)){
					printf("No valid file name\n");
					return; // no valid filename
				}
				
				while(testChar != 0){
					filename[wallE] = (char)testChar;
					buffadd+=1;
					wallE++;
					if(!machine->ReadMem(buffadd, 1, &testChar)) return;	// it broke so leave
				}
				
				filename[wallE] = (char)0;
				if(strchr(filename, '!') || strchr(filename, '@') || strchr(filename, '#') || strchr(filename, '$') || 
				strchr(filename, '%') || strchr(filename, '^') || strchr(filename, '&') || strchr(filename, '*') || 
				strchr(filename, '(') || strchr(filename, ')') || strchr(filename, '-') || strchr(filename, '_') || 
				strchr(filename, '=') || strchr(filename, '+')){
					canCreate = false;
					sprintf(filename, "\0");
					printf("Cannot create a file with the characters !@#$%^&*()-_+=\n");
				}
				
				fileSize = arg2;		
				if(canCreate == true){
					fileSystem->Create(filename, fileSize);
				}
			break;
		
			/*
			OpenFileId Open (char *filename)

			Open the file named filename and return an OpenFileId to be used as a handle 
			for the file in subsequent Read or Write calls. Each process is to have a set 
			of OpenFileIds associated with its state and the necessary bookkeeping to map 
			them into the file system's internal way of identifying open files. This call 
			differs from Unix in that it does not specify any access mode (open for writing, 
			open for reading, etc.) 
			*/
			case SC_Open :
			//	printf("System Call OPEN:\n");
				buffadd = machine->ReadRegister(4);	/* only one argument, so that's in R4 */
				if(!machine->ReadMem(buffadd,1,&testChar)){
					printf("No valid file name\n");
					return; // no valid filename
				}
				
				while(testChar != 0){
					filename[wallE] = (char)testChar;
					buffadd+=1;
					wallE++;
					if(!machine->ReadMem(buffadd, 1, &testChar)) return;	// it broke so leave
				}
				
				filename[wallE] = (char)0;
				if(strchr(filename, '!') || strchr(filename, '@') || strchr(filename, '#') || strchr(filename, '$') || 
				strchr(filename, '%') || strchr(filename, '^') || strchr(filename, '&') || strchr(filename, '*') || 
				strchr(filename, '(') || strchr(filename, ')') || strchr(filename, '-') || strchr(filename, '_') || 
				strchr(filename, '=') || strchr(filename, '+')){
					canCreate = false;
					sprintf(filename, "\0");
					printf("Invalid filename\n");
					break;
				}
				
				openedFile = fileSystem->Open(filename);
				if(openedFile != NULL){
				//	printf("File opened correctly\n");
					numOPEN++;
					myOFiles->addFile(openedFile, numOPEN);
				}
				else{
				//	printf("Could not open file\n");
				}
			//	printf("The Size is %d \n", myOFiles->getSize());
				machine->WriteRegister(2, numOPEN);
			break;
		
			// close the file
			// Clean up the "bookkeeping" data structures representing the open file. 
			case SC_Close :
				if(myOFiles->getSize() == 0){
				//	printf("There are no Open Files SIR!\n");
					break;
				}
			//	printf("System Call CLOSE:\n");
				checkIt = arg1;
			//	printf("CheckIt is %d \n", checkIt);
				tempOpen = myOFiles->find(checkIt);
			//	printf("Is Empty %d\n", myOFiles->getSize());
				if(tempOpen == NULL){
					printf("Could not find specified Opened File\n");
				}
				else{
					printf("Closing Opened File ID number %d", checkIt);
					myOFiles->removeFile(checkIt);
					if(tempOpen != NULL){
						delete tempOpen;
					}
					//fileSystem->Remove(checkIt);
				}
			break;
			
			// just the file
			case SC_Ls :		
				if(hasL == true){
				//	printf("System Call LS -l:\n");
					fileSystem->SYS_LS_L();
					hasL = false;
					delete filename;
					filename = NULL;
				}
				else{
				//	printf("System Call LS:\n");
					fileSystem->SYS_LS();
					delete filename;
					filename = NULL;
				}
			break;
			
			// returns the current working directory like in unix
			case SC_Pwd :
			//	printf("System Call PWD:\n");
				fileSystem->PWD_PRIME();
				delete filename;
				filename = NULL;
			break;		
			
			case SC_mkdir :
				//printf("SysCall: MKDIR \n");
			//	printf("Arg1: %s\n", newArg1);
				fileSystem->CreateDir(newArg1);
				delete newArg1;
				newArg1 = NULL;
				delete filename;
				filename = NULL;
				//sprintf(newArg1, "\0");
			break;
			
			case SC_rmdir :
				//printf("SysCall: RMDIR \n");
				//printf("Arg1: %s\n", newArg1);
				fileSystem->RemoveDir(newArg1);
				delete newArg1;
				newArg1 = NULL;
				delete filename;
				filename = NULL;
			break;
			
			case SC_cd:	
				
			//	printf("SysCall: CD \n");
			//	printf("Arg1: %s\n", newArg1);
				for(int x = 0; x < strlen(newArg1); x++){
					if(newArg1[x] == '/'){
						useParsing = true;
					}
				}
				if(useParsing == false){
					fileSystem->changeDirNoPath(newArg1);
				}
				else{
					newDir1 = fileSystem->parsePath(newArg1);
					if(newDir1 != NULL){
						fileSystem->changeDir(newDir1);
					}
					else{
						printf("ERROR\n");
					}
				}
				useParsing = false;
				delete newArg1;
				newArg1 = NULL;
				delete filename;
				filename = NULL;
			break;
			
			case SC_rm:
			//	printf("SysCall: RM \n");
			//	printf("filename: %s \n", filename);
			//	printf("Arg1: %s\n", newArg1);
				didSYSRM = fileSystem->Remove(newArg1);
				if(didSYSRM == false){
					printf("failed to remove the file\n");
				}
				delete newArg1;
				newArg1 = NULL;
				delete filename;
				filename = NULL;
			break;
			
			case SC_cp:

			//	printf("SysCall: CP \n");
			//	printf("Arg1: %s\n", newArg1);
				if(strcmp(newArg2, ".") == 0){
					for(int SoX = strlen(newArg1)-1; newArg1[SoX] != '/' && SoX != 0; SoX--){
						getFile12[goThrough] = newArg1[SoX];
						newArg1[SoX] = '\0';
			//			printf("%s\n", newArg1);
						specCount = SoX;
						goThrough++;
					}
					goThrough--;
			//		printf("The getFile12 %s \n", getFile12);
			//		printf("Go Through %d\n", goThrough);
					specCharGetter = new char[strlen(getFile12)];
					for(int p = 0; goThrough >= 0; p++){
						specCharGetter[p] = getFile12[goThrough];
			//			printf("The File at %c \n", getFile12[goThrough]);
						goThrough--;
					}
			//		printf("specCharGetter %s \n", specCharGetter);
					
					newArg1[specCount-1] = '\0';
					getSectNew1 = fileSystem->parsePath(newArg1);
					mySpecialOPFile = fileSystem->getOpenFileBySect(specCharGetter, getSectNew1);
					fileSystem->CreateForDirectory(mySpecialOPFile->Length(), specCharGetter, fileSystem->getCurrDirSector());
				}
				else{
					specCount = 0;
					for(int SoX = strlen(newArg1)-1; newArg1[SoX] != '/' && SoX != 0; SoX--){
						getFile12[goThrough] = newArg1[SoX];
						newArg1[SoX] = '\0';
				//		printf("%s\n", newArg1);
						specCount = SoX;
						goThrough++;
					}
					specCharGetter = new char[strlen(getFile12)];
					for(int p = 0; goThrough != 0; p++){
						specCharGetter[p] = getFile12[goThrough];
						goThrough--;
					}
					newArg1[specCount-1] = '\0';
					getSectNew1 = fileSystem->parsePath(newArg1);
					getSectNew2 = fileSystem->parsePath(newArg2);
					mySpecialOPFile = fileSystem->getOpenFileBySect(specCharGetter, getSectNew1);
				//	printf("getSectNew1 : %d");
					fileSystem->CreateForDirectory(mySpecialOPFile->Length(), specCharGetter, getSectNew2);
					
				}
				
				delete newArg1;
				newArg1 = NULL;
				delete newArg2;
				newArg2 = NULL;
				delete filename;
				filename = NULL;
			break;
			
			case SC_mv:
			//	printf("SysCall: MV \n");
			//	printf("Arg1: %s\n", newArg1);
				if(strcmp(newArg2, ".") == 0){
					for(int SoX = strlen(newArg1)-1; newArg1[SoX] != '/' && SoX != 0; SoX--){
						getFile12[goThrough] = newArg1[SoX];
						newArg1[SoX] = '\0';
			//			printf("%s\n", newArg1);
						specCount = SoX;
						goThrough++;
					}
					goThrough--;
			//		printf("The getFile12 %s \n", getFile12);
			//		printf("Go Through %d\n", goThrough);
					specCharGetter = new char[strlen(getFile12)];
					for(int p = 0; goThrough >= 0; p++){
						specCharGetter[p] = getFile12[goThrough];
			//			printf("The File at %c \n", getFile12[goThrough]);
						goThrough--;
					}
			//		printf("specCharGetter %s \n", specCharGetter);
					
					newArg1[specCount-1] = '\0';
					getSectNew1 = fileSystem->parsePath(newArg1);
					mySpecialOPFile = fileSystem->getOpenFileBySect(specCharGetter, getSectNew1);
					fileSystem->CreateForDirectory(mySpecialOPFile->Length(), specCharGetter, fileSystem->getCurrDirSector());
				}
				else{
					specCount = 0;
					for(int SoX = strlen(newArg1)-1; newArg1[SoX] != '/' && SoX != 0; SoX--){
						getFile12[goThrough] = newArg1[SoX];
						newArg1[SoX] = '\0';
				//		printf("%s\n", newArg1);
						specCount = SoX;
						goThrough++;
					}
					specCharGetter = new char[strlen(getFile12)];
					for(int p = 0; goThrough != 0; p++){
						specCharGetter[p] = getFile12[goThrough];
						goThrough--;
					}
					newArg1[specCount-1] = '\0';
					getSectNew1 = fileSystem->parsePath(newArg1);
					getSectNew2 = fileSystem->parsePath(newArg2);
					removeFromDir(specCharGetter, getSectNew1);
					mySpecialOPFile = fileSystem->getOpenFileBySect(specCharGetter, getSectNew1);
				//	printf("getSectNew1 : %d");
					fileSystem->CreateForDirectory(mySpecialOPFile->Length(), specCharGetter, getSectNew2);
					
				}
				delete newArg1;
				newArg1 = NULL;
				delete filename;
				filename = NULL;
			break;
			
			case SC_cat:
				fileSystem->RevertSysCall();
				char *myBuff;
				char *buff2;
				char buff3[10];
				int getRead;
				int file1Len;
				int file2Len;
				int file3Len;
				int myChar;
				int amountRead;
								
			//	printf("SysCall: CAT\n");
				if(cat2 == true){
			//		printf("cat has 2 args\n");
			//		printf("Arg1: %s\n", newArg1);
			//		printf("Arg2: %s\n", newArg2);
			//		printf("Arg3: %s\n", newArg3);
					
			//		printf("Before the OPEN\n");
					openedFile1 = fileSystem->Open(newArg1);
					int x = 72;
			//		printf("before the while\n");
				//		printf("the x %d \n", x);
					
					//file1Len = openedFile1->Length();
					openedFile2 = fileSystem->Open(newArg2);
					
					if(openedFile2 == NULL){
						printf("---------------------It is null----------------------------\n");
						return;
					}
					
					if(openedFile1 == NULL){
						printf("-------------------File1 is null---------------------------\n");
						return;
					}
					
					
			//		printf("Before the Length\n");
					file1Len = openedFile1->Length();
					file2Len = openedFile2->Length();
					
			//		printf("The files length is %d \n", file2Len);
					
					//myChar = openedFile2->Read(myBuff, 1);
					
					sprintf(buff3, "dummyF");
					
			//		printf("Before the if\n");
					if((strcmp(newArg1, newArg3) == 0) || (strcmp(newArg2, newArg3) == 0)){

						if((strcmp(newArg1, newArg3) == 0)){

							fileSystem->Create(buff3, (file1Len + file2Len));
							openedFile3 = fileSystem->Open(buff3);
								
							file3Len = openedFile3->Length();
							
							int gpi = 0;
							char *buffer = new char[TransferSize];
				//			printf("FILE LENGTH 1 %d\n", file1Len);
				//			printf("FILE LENGTH 2 %d\n", file2Len);
							int loop = 0;
							while ((amountRead = openedFile1->Read(buffer, TransferSize)) > 0){
								for (gpi = 0; gpi < amountRead; gpi++){
									myBuff = &buffer[gpi];
									openedFile3->WriteAt(myBuff, 1, loop);
									printf("%c", buffer[gpi]);
									loop++;
								}										
							}
							gpi = loop;
				//			printf("gpi: %d \n", gpi);
				//			printf("Length of one: %d \n", file1Len);
				//			printf("Length of two: %d \n", file2Len);
							while ((amountRead = openedFile2->Read(buffer, TransferSize)) > 0){
								for (int o = 0; o < amountRead; o++){
									myBuff = &buffer[o];
									openedFile3->WriteAt(myBuff, 1, gpi);
									gpi++;
									printf("%c", buffer[o]);
								}										
							}

							file1Len = openedFile1->Length();
					//		printf("New file1 len: %d \n", file1Len);
							
							delete openedFile1;
							
							fileSystem->Remove(newArg1);
							
							fileSystem->Create(newArg1, file3Len);
							
							openedFile1 = fileSystem->Open(newArg1);
							
							int newHope = 0;
							
							while ((amountRead = openedFile3->Read(buffer, TransferSize)) > 0){
								for (int v = 0; v < amountRead; v++){
									myBuff = &buffer[v];
									openedFile1->WriteAt(myBuff, 1, newHope);
									newHope++;
									printf("%c", buffer[v]);
								}										
							}
							
							delete openedFile3;
							
							fileSystem->Remove(buff3);
							
							
							
							delete buffer;

							delete openedFile2;		// close the Nachos file
							delete openedFile1;
						}
						
						if(strcmp(newArg2, newArg3) == 0){
						
							fileSystem->Create(buff3, (file1Len + file2Len));
							openedFile3 = fileSystem->Open(buff3);
								
							file3Len = openedFile3->Length();
							
							int gpi = 0;
							char *buffer = new char[TransferSize];
					//		printf("FILE LENGTH 1 %d\n", file1Len);
					//		printf("FILE LENGTH 2 %d\n", file2Len);
							int loop = 0;
							while ((amountRead = openedFile1->Read(buffer, TransferSize)) > 0){
								for (gpi = 0; gpi < amountRead; gpi++){
									myBuff = &buffer[gpi];
									openedFile3->WriteAt(myBuff, 1, loop);
									printf("%c", buffer[gpi]);
									loop++;
								}										
							}
							gpi = loop;
					//		printf("gpi: %d \n", gpi);
					//		printf("Length of one: %d \n", file1Len);
					//		printf("Length of two: %d \n", file2Len);
							while ((amountRead = openedFile2->Read(buffer, TransferSize)) > 0){
								for (int o = 0; o < amountRead; o++){
									myBuff = &buffer[o];
									openedFile3->WriteAt(myBuff, 1, gpi);
									gpi++;
									printf("%c", buffer[o]);
								}										
							}

							file2Len = openedFile2->Length();
					//		printf("New file2 len: %d \n", file2Len);
							
							delete openedFile2;
							
							fileSystem->Remove(newArg2);
							
							fileSystem->Create(newArg2, file3Len);
							
							openedFile2 = fileSystem->Open(newArg2);
							
							int newHope = 0;
							
							while ((amountRead = openedFile3->Read(buffer, TransferSize)) > 0){
								for (int v = 0; v < amountRead; v++){
									myBuff = &buffer[v];
									openedFile2->WriteAt(myBuff, 1, newHope);
									newHope++;
									printf("%c", buffer[v]);
								}										
							}
							
							delete openedFile3;
							
							fileSystem->Remove(buff3);
							
							
							
							delete buffer;

							delete openedFile2;		// close the Nachos file
							delete openedFile1;
						
						}
					}
					else{							// create a new file to cat the shit
					//	printf("IN else\n");
						openedFile3 = fileSystem->Open(newArg3);
						if(openedFile3 == NULL){			// if the third file doesnt exist make it
							fileSystem->Create(newArg3, (file1Len + file2Len + 15));
							openedFile3 = fileSystem->Open(newArg3);
						}
						file3Len = openedFile3->Length();
						int cpi = 0;
						char *buffer = new char[TransferSize];
					//	printf("FILE LENGTH 1 %d\n", file1Len);
					//	printf("FILE LENGTH 2 %d\n", file2Len);
						int countME = 0;
						while ((amountRead = openedFile1->Read(buffer, TransferSize)) > 0){
							for (cpi = 0; cpi < amountRead; cpi++){
								myBuff = &buffer[cpi];
								openedFile3->WriteAt(myBuff, 1, countME);
								printf("%c", buffer[cpi]);
								countME++;
							}										
						}
						cpi = countME;
					//	printf("CPI: %d \n", cpi);
					//	printf("Length of one: %d \n", file1Len);
					//	printf("Length of two: %d \n", file2Len);

						while ((amountRead = openedFile2->Read(buffer, TransferSize)) > 0){
							for (i = 0; i < amountRead; i++){
								myBuff = &buffer[i];
								openedFile3->WriteAt(myBuff, 1, cpi);
								cpi++;
								printf("%c", buffer[i]);
							}										
						}

						file1Len = openedFile1->Length();
					//	printf("New file1 len: %d \n", file1Len);
						
						delete buffer;

						delete openedFile2;		// close the Nachos file
						delete openedFile1;
						delete openedFile3;
					}
					
					delete newArg1;
					delete newArg2;
					delete newArg3;
					delete filename;
					newArg1 = NULL;
					newArg2 = NULL;
					newArg3 = NULL;
					filename = NULL;
					cat2 = false;
				}
				else{								// if cat only has one argument
				//	printf("cat has 1 arg\n");
				//	printf("newArg1 = %s\n", newArg1);
					openedFile = fileSystem->Open(newArg1);
					if(openedFile != NULL){
					//	printf("File opened correctly\n");
					//	numOPEN++;
					//	myOFiles->addFile(openedFile, numOPEN);
					//	printf("Before While\n");
					//	do{
						//	printf("In While");
				//			getRead = SRead((int)myBuff, 256, numOPEN);
						//	Write(myBuff,getRead, numOPEN);
						//	printf("The number %d \n", getRead);
				//			printf("%c", (char)getRead);
							Print(newArg1);
					//		if(getRead > 0)
					//			break;
					//	}while(true);
					//	printf("After While\n");
					}
					
					else{
						printf("Could not open file\n");
						
					}
					delete newArg1;
					delete filename;
					newArg1 = NULL;
					filename = NULL;
				}
				
			break;	// end of cat
			
			
			default :
			//Unprogrammed system calls end up here
			break;
			
			

		
		}         
		break;

	case ReadOnlyException :
		puts ("ReadOnlyException");
		if (currentThread->getName() == "main")
		ASSERT(FALSE);  //Not the way of handling an exception.
		//SExit(1);
		break;
	case BusErrorException :
		puts ("BusErrorException");
		if (currentThread->getName() == "main")
		ASSERT(FALSE);  //Not the way of handling an exception.
		//SExit(1);
		break;
	case AddressErrorException :
		puts ("AddressErrorException");
		if (currentThread->getName() == "main")
		ASSERT(FALSE);  //Not the way of handling an exception.
		//SExit(1);
		break;
	case OverflowException :
		puts ("OverflowException");
		if (currentThread->getName() == "main")
		ASSERT(FALSE);  //Not the way of handling an exception.
		//SExit(1);
		break;
	case IllegalInstrException :
		puts ("IllegalInstrException");
		//if (currentThread->getName() == "main")
		ASSERT(FALSE);  //Not the way of handling an exception.
		//SExit(1);
		break;
	case NumExceptionTypes :
		puts ("NumExceptionTypes");
		if (currentThread->getName() == "main")
		ASSERT(FALSE);  //Not the way of handling an exception.
		//SExit(1);
		break;

		default :
		//      printf("Unexpected user mode exception %d %d\n", which, type);
		//      if (currentThread->getName() == "main")
		//      ASSERT(FALSE);
		//      SExit(1);
		break;
	}
	delete [] ch;
}


int SRead(int addr, int size, int id)  //input 0  output 1
{

//	printf("In SREAD\n");

	char currChar;
	char buffer[size+10];
	char tempBuffer[size + 10];
	char temp[size+11];
	int num,Result;

	int newProc;
	
	int i = 0;
	int b;
	
	//buffer = NULL;
	
	//read from keyboard, try writing your own code using console class.
	if (id == 0)
	{
		currChar = getchar();
		while(currChar != '\n'){
			buffer[i] = currChar;
			currChar = getchar();
			i++;
		}
	//	buffer[i++] = '\n';
	
		for(int l = i; l < size+10; l++){
			buffer[l] = NULL;
		}
		buffer[i+1] = '\0';
	//	printf("buffer is %s \n", buffer);
		
		
		for(int x = 0; x < i; x++){
		//	printf("x is %d \n", x);
		//	printf("The char is %c \n", buffer[x]);
			machine->WriteMem((addr+x), 1, (int) buffer[x]);
			if(buffer[x]=='\0') break;
		}
		
	//	printf("Result is %d \n", i);
		return i;
	}		
	
	//read from a unix file, later you need change to nachos file system.
	else
	{

		for(num=0;num<size;num++){
			Read(id,&buffer[num],1);
			machine->WriteMem((addr+num), 1, (int) buffer[num]);
			if(buffer[num]=='\0') break;
		}
		return num;

	}
	
//	}
}



void SWrite(char *buffer, int size, int id)
{
	//write to terminal, try writting your own code using console class.
//	if (id == 1)
	printf("%s", buffer);
	//write to a unix file, later you need change to nachos file system.
	if (id >= 2)
	WriteFile(id,buffer,size);
}

// end FA98
















